package ren.kane.phoenix.util.reflect;

import java.lang.reflect.Method;

/**
 * @author renrk(1275) on 2019-08-14 8:37 AM
 **/
public class MethodTest {

    private static void testGetDeclaredMethod() {
        try {
            Class<?> clazz = Person3.class;
            Object person = clazz.newInstance();
            Method mSetName = clazz.getDeclaredMethod("setName", String.class);
            Method mGetName = clazz.getDeclaredMethod("getName");
            Method mSetAge = clazz.getDeclaredMethod("setAge", int.class);
            Method mGetAge = clazz.getDeclaredMethod("getAge");
            Method mSetGender = clazz.getDeclaredMethod("setGender", Gender.class);
            Method mGetGender = clazz.getDeclaredMethod("getGender");

            mSetName.invoke(person, "Tom");
            mSetAge.invoke(person, 30);
            mSetGender.setAccessible(true);
            mSetGender.invoke(person, Gender.MALE);

            String name = (String) mGetName.invoke(person);
            Integer age = (Integer) mGetAge.invoke(person);
            mGetGender.setAccessible(true);
            Gender gender = (Gender) mGetGender.invoke(person);
            System.out.printf("%-30s: person=%s, name=%s, age=%s, gender=%s\n", "getDeclaredMethod()", person, name, age, gender);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testGetMethod() {
        try {
            Class<?> clazz = Person3.class;
            Object person = clazz.newInstance();
            Method mSetName = clazz.getMethod("setName", String.class);
            Method mGetName = clazz.getMethod("getName");

            mSetName.invoke(person, "Tom");
            String name = (String) mGetName.invoke(person);
            System.out.printf("%-30s: person=%s, name=%s\n", "getMethod()", person, name);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testGetEnclosingMethod() {
        try {
            Class<?> clazz = Person3.class;
            Object person = clazz.newInstance();
            Method mGetInner = clazz.getDeclaredMethod("getInner");
            mGetInner.invoke(person);
            System.out.printf("%-30s: person=%s\n", "getEnclosingMethod", person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        testGetDeclaredMethod();
        testGetMethod();
        testGetEnclosingMethod();
    }
}

class Person3 {
    private String name;
    private int age;
    private Gender gender;

    public Person3() {
        this("unknown", 0, Gender.FEMALE);
    }

    public Person3(String name, int age, Gender gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected int getAge() {
        return age;
    }

    protected void setAge(int age) {
        this.age = age;
    }

    private Gender getGender() {
        return gender;
    }

    private void setGender(Gender gender) {
        this.gender = gender;
    }

    public void getInner() {
        class InnerB {
        }
        Class clazz = InnerB.class;
        Method method = clazz.getEnclosingMethod();
        System.out.println("call--\"getInner()\" method=" + method);
    }

    @Override
    public String toString() {
        return "(" + name + ", " + age + ", " + gender + ")";
    }
}
